#include "hal_function.h"
#include "oled.h"

OledHandle OLED_Handle;


void OLED_DataTObit(int x,int y, int color,void *gram)
{


    uint8_t bitoffset;
    uint16_t bytebase;
    uint16_t byte;
    uint8_t *buff = gram;

    if((x < SSD1306_WEIGHT) && (y < SSD1306_HEIGHT))
    bytebase = (y/8) * SSD1306_WEIGHT;
    byte = bytebase + x;
    bitoffset = y % 8;
    buff[byte] &=  ~(1<<bitoffset);
    if(color)
    {
        buff[byte] |=  (1<<bitoffset);
    }
}



/*Flush the content of the internal buffer the specific area on the display
 *You can use DMA or any hardware acceleration to do this operation in the background but
 *'lv_disp_flush_ready()' has to be called when finished.*/
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/

    int32_t x;
    int32_t y;
    for(y = area->y1; y <= area->y2; y++) {
        for(x = area->x1; x <= area->x2; x++) {
            /*Put a pixel to the display. For example:*/
            /*put_px(x, y, *color_p)*/
            OLED_Write(x,y,(int)(color_p->full));
            color_p++;
        }
    }
    OLED_UPDATA();
    /*IMPORTANT!!!
     *Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}

void OLED_LV_INIT()
{
    /*-----------------------------
     * Create a buffer for drawing
     *----------------------------*/
    lv_disp_drv_init(&OLED_Handle.dis_drv);                    /*Basic initialization*/
    OLED_Handle.gram = malloc(((SSD1306_WEIGHT * SSD1306_HEIGHT)) / 8);
    OLED_Handle.disbuf = malloc(OLED_LV_DIS_BUF_SIZE);
    if(OLED_Handle.disbuf)
    {
         /*Set up the functions to access to your display*/
        lv_disp_draw_buf_init(&OLED_Handle.draw_buf, OLED_Handle.disbuf, NULL,OLED_LV_DIS_BUF_SIZE);  /*Initialize the display buffer.*/
        /*Set the resolution of the display*/
        OLED_Handle.dis_drv.hor_res = SSD1306_WEIGHT;
        OLED_Handle.dis_drv.ver_res = SSD1306_HEIGHT;

        /*Used to copy the buffer's content to the display*/
        OLED_Handle.dis_drv.flush_cb = disp_flush;

        /*Set a display buffer*/
        OLED_Handle.dis_drv.draw_buf = &OLED_Handle.draw_buf;

        /*Finally register the driver*/
        lv_disp_drv_register(&OLED_Handle.dis_drv);
    }
}



void OLED_Write(int x,int y,int color)
{
    OLED_DataTObit(x,y,color,OLED_Handle.gram);
}

void OLED_UPDATA()
{
    ssd1306_UpdataScreen(OLED_Handle.gram);
}
